#include<iostream>
#include<vector>
#include<cstring>
#include<unistd.h>
#include<pthread.h>
#include<cstdio>
using namespace std;
#define NUM 5

//写这个抢票是为了引出互斥锁的概念

//要使用多线程就要把多个线程对象组织起来，所以我们要先描述，也就先封装线程的对象
class threadData
{
public:
    threadData(int number)
    {
        threadname_="thread-"+to_string(number);
        
    }
public:
    string threadname_;
    
};

//设置票的总量：
int tickets=1000;

//使用多线程模拟多个抢票：
void* getTickets(void *args)
{
    threadData *td=static_cast<threadData*>(args);
    const char* name=td->threadname_.c_str();//string转化为const char*类型要使用c_str()函数
    while(true)
    {
        if(tickets>0)
        {
            usleep(1000);
            printf("who=%s,get a ticket:%d\n",name,tickets);
            tickets--;
        }
        else
        {
            break;
        }
    }
    printf("%s,quit\n",name);
    return nullptr;
}



//抢票的结果是完全错误且混乱的：现象：1，有一些票被重复抢了多次，有一些票号没有被抢，也就是抢到的票数总和不等于总票数  2，票被抢到了负数
//解释：1，由于多个线程在执行的时候是无序的，是按照一定要求调度的，并且抢票的核心过程不是原子的，此时抢票的函数不是可重入的，所以多个执行流同时访问的时候会出现各种错误情况
//2，票数出现负数：有可能这些进程都刚好在判断完票数等于1的时候进入了抢票，此时某个线程就会抢到编号为1的票，下一个线程会抢到编号为0的票，依次类推，会抢到负数的票

//总之：一切的错误都是因为抢票的过程不是原子的，如果每个进程一旦进行抢票就会直接让ticks--一起在同一时刻完成，不会被调度打断的话，此时抢票的过程才会恢复正确
//所以我们要加互斥锁mutex

int main()
{
    vector<pthread_t>tids;
    vector<threadData*>thread_datas;
    //创建多线程：
    for(int i=1;i<=NUM ;i++)//会创建出NUM个线程去执行抢票的任务
    {
        pthread_t tid;
        threadData*td=new threadData(i);
        thread_datas.push_back(td);//线程的信息放在动态数组中管理起来
        pthread_create(&tid,nullptr,getTickets,thread_datas[i-1]);
        tids.push_back(tid);//把tid放在动态数组中管理起来
    }
    for(auto e:tids)//释放多线程
    {
        pthread_join(e,nullptr);
    }
    //释放申请的空间：
    for(auto e:thread_datas)
    {
        delete e;
    }

    return 0;
}
